注: 以下做法只是为了尽量避免和 QML 内置属性重命, 以及为了更方便开发者通过名字就能确定它的一些特征.
_xxx 下划线开头的变量用于暗示这是一个 "私有" 变量, 请避免让它被外部文件直接访问.
xxxxxxxxxx1// === A.qml ===2import QtQuick 2.1534Item {5property alias p_size: _txt.font.pixelSize6property alias p_text: _txt.text7Text { id: _txt }8}910// === B.qml ===11import QtQuick 2.151213Item {14A {15// 在 B.qml 中, 是访问不到 A.qml 的 id 为 _txt 的对象的. 这也是我们希望16// 看到的结果.17// 不过我们可以访问和修改 p_size 和 p_text.18p_size: 1819p_text: "hello world"20}21}22
xxxxxxxxxx61import QtQuick 2.1523Item {4property string p_text: ""5Text { text: p_text }6}
x1import QtQuick 2.1523Item {4property bool __active: false // `__active` 只允许在该文件内使用, 请不要在5// 外部调用时修改它.67Rectangle {8color: __active ? "white" : "gray"9width: 100; height: 1001011MouseArea {12anchors.fill: parent13onClicked: {14__active = !__active15}16}17}18}19
xxxxxxxxxx1// === D:/workspace/my_prj/ui/page1/Element.qml ===2import QtQuick 2.1534Item {5id: _root6// 相对路径是相对于当前项目 (my_prj) 的路径.7objectName: "ui/page1/Element.qml#_root"89Text {10id: _txt11objectName: "ui/page1/Element.qml#_txt"12text: ""13}14}
xxxxxxxxxx171// === A.qml ===2import QtQuick 2.1534Item {5// 推荐6property alias p_text1: _txt1.text7Text {8id: _txt19}1011// 不推荐12property string p_text2: ""13Text {14id: _txt215text: p_text216}17}18
x1// === A.qml ===2import QtQuick 2.1534Item {5property alias obj_Text: _txt67Text {8id: _txt9}10}1112// === B.qml ===13import QtQuick 2.151415Item {16A {17p_text: "hello world"1819// 在 B.qml 中, 不能直接访问 A.qml 的 id 为 _txt 的对象, 但可以通过20// obj_Text 访问到它.21obj_Text { // 这里相当于引用了 A.Item.Text 对象.22font.bold: true23}24}25}26
xxxxxxxxxx381// === A.qml ===2import QtQuick 2.1534Rectangle {5id: _rect6color: "white"7width: 100; height: 10089signal fn_clicked(string color)1011MouseArea {12onClicked: {13fn_clicked(_rect.color)14}15}16}1718// === B.qml ===19import QtQuick 2.152021Item {22width: 500; height: 5002324function fn_showColor(color) {25_txt.text = color // 当点击 A 对象, 会使 _txt 对象的文字显示为 A 的颜色.26}2728A {29fn_clicked.connect(fn_showColor)30}3132Text {33id: _txt34anchors.centerIn: parent35text: "what's the color?"36}37}38
id 始终位于第一行, objectName 始终位于第二行
xxxxxxxxxx1import QtQuick 2.1523Text {4id: _txt5objectName: "my_txt"6}
以下属性按照指定顺序置顶显示: id > objectName > name > source (常见于 Loader 对象) > target (常见于 State 对象) > 其他内建属性 (按照字母表顺序) > 自定义属性 (按照字母表顺序).
x1import QtQuick 2.1523Rectangle {4id: _root5objectName: "my_item"6anchors.left: parent7anchors.margins: 128anchors.top: parent910property bool p_active: false1112states: [13State {14name: "defaultState"15when: p_active16PropertyChanges {17target: _root18color: "white"19x: 1020y: 1021}22}23]2425Loader {26id: _item127source: "./Items/Item1.qml"28anchors.centerIn: parent29}30}31
对于关联性强的元素, 可以合并到一行书写 (在单行内的属性书写顺序无需按照字母表顺序)
x1import QtQuick 2.1523Rectangle {4id: _rect5color: "#FAFAFA"6width: 100; height: 100 // 并到了一行书写.7x: 10; y: 10; z: 1 // 并到了一行书写.89property alias p_color: _rect.color10property int p_index: 011property string p_text: ""12signal fn_clicked(string color)1314Text {15id: _txt16anchors.centerIn: parent17text: p_text1819font.bold: true20font.family: "Microsoft YaHei UI"21font.pixelSize: 1822}23}
原则: QML 只负责布局和 UI 的呈现, 模型 (数据) 以及模型交互的逻辑全部由 Python 实现.
具体的实现讲解见这篇文章: TODO. 这里从设计原则的角度说一下应该怎么做.
首先, 这个思路是不可取的: Python 通过 engine 获取到 Grid 对象, 并操作 Grid 的 add 方法, 渲染并插入一个 MyItem 对象.
这个思路的问题有两个:
所以, 一个可参考的思路是这样的:
QML 端: Grid 内套一个 Repeater 对象 (因为 Repeater 有 model 属性), Repeater 的 delegate 属性 (代理对象) 设为 MyItem
Python 端: Python 通过 engine 获取到 Repeater 对象, 对其 model 进行操作, 插入一条 MyItem 的数据. QML 自动完成 UI 的更新.